package dryven.request;

import dryven.model.di.DependencyService;
import dryven.request.controller.ControllerDescription;
import dryven.request.controller.result.ActionResult;
import dryven.request.controller.result.ForwardResult;
import dryven.request.http.Request;
import dryven.request.http.Response;
import dryven.request.routing.RoutingService;

public class RequestFrontController implements FrontController {
	private RoutingService _router;
	private DependencyService _dependencyService;
	private RequestLifeCycleListener _listener;

	public RequestFrontController(RoutingService router, DependencyService dependencyService, RequestLifeCycleListener l) {
		super();
		_router = router;
		_dependencyService = dependencyService;
		_listener = l;
	}

	public void handleRequest(Request req, Response resp) {
		
		if(_listener!=null) {
			_listener.beforeRouting(req);
		}
		
		ControllerDescription cd = _router.routeToController(req, resp);
		
		if(_listener!=null) {
			_listener.startRequest(req, cd);
		}
		
		if(cd==null) {
			resp.setStatus(404);
			if(_listener!=null) {
				_listener.endRequest(req);
			}
			return;
		}
		
		//TODO catch possible exceptions here!
		ActionResult result = new ForwardResult(cd);
		while(result!=null) {
			//inject dependencies in ActionResult by calling all injectDependencies methods
			_dependencyService.injectDependencies(req, result);
			
			if(_listener!=null) {
				_listener.startResult(req, result);
			}
			
			result = result.process(req, resp);
			
			if(_listener!=null) {
				_listener.endResult(req, result);
			}
		}
		
		if(_listener!=null) {
			_listener.endRequest(req);
		}
	}

	@Override
	public void shutdown() {
		if(_listener!=null) {
			_listener.shutdown();
		}
	}
	
	
}
